package controllers;

import play.*;
import play.mvc.*;
import play.libs.*;

import java.text.*;
import java.util.*;

import org.joda.time.*;

import models.*;

public class Application extends Controller 
{
	/**
	 * This method populates the rendering args space with
	 * the "daysto" and "dfnum" values expected by the menu
	 */
	@Before
	public static void populateConInfo()
	{
    	final F.Tuple<String,String> daysCalcResult = daysCalc();
    	renderArgs.put("daysto", daysCalcResult._1);
    	renderArgs.put("dfnum", daysCalcResult._2);    
	}

	// ========================================================
	// Controllers
	// ========================================================
    public static void index() 
    {
        render();
    }
    
    public static void about() 
    {
    	render();
    }
    
    public static void board() 
    {
    	render();
    }
	
	public static void bylaws() 
    {
    	render();
    }
    
    public static void convens()
    {
    	List<Convention> conventions = Convention.findAll();
    	render(conventions);
    }

	public static void commun() 
    {
    	render();
    }

    public static void elections()
    {
        render();
    }

    // ========================================================
	// Application utility methods
	// ========================================================    
    public static int daysBetween(Date fromDate, Date toDate)
    {
    	DateTime from = new DateTime(fromDate.getYear()+1900,
    		fromDate.getMonth(),
    		fromDate.getDate(),
    		0,
    		0);
    	DateTime to = new DateTime(toDate.getYear()+1900,
    		toDate.getMonth(),
    		toDate.getDate(),
    		0,
    		0);
    	return Math.abs(Days.daysBetween(from, to).getDays());
    }
    
    public static String romanNumeralOf(int arabicNum)
    {
		// ========================================================
		// Implementation adapted/stolen from 
		// www.roseindia.net/java/java-tips/45examples/misc/roman/roman.shtml
		
	    // Parallel arrays used in the conversion process.
    	final String[] RCODE = {"M", "CM", "D", "CD", "C", "XC", "L",
    	                        "XL", "X", "IX", "V", "IV", "I"};
    	final int[]    BVAL  = {1000, 900, 500, 400,  100,   90,  50,
        	                    40,   10,    9,   5,   4,    1};
    
        if (arabicNum <= 0 || arabicNum >= 4000) 
        {
            throw new NumberFormatException("Value outside roman numeral range.");
        }
        String roman = "";         // Roman notation will be accumualated here.
        
        // Loop from biggest value to smallest, successively subtracting,
        // from the binary value while adding to the roman representation.
        for (int i = 0; i < RCODE.length; i++) 
        {
            while (arabicNum >= BVAL[i]) 
            {
                arabicNum -= BVAL[i];
                roman  += RCODE[i];
            }
        }
        return roman;
    }

    public static String dragonflightNumberOf(int year)
    {
    	return romanNumeralOf(year - 1980 + 1);
    }
    
    public static ConInfo getConInfo()
    {
    	// Fetch ConInfo for this year
    	List<ConInfo> conList = ConInfo.find("order by year desc").fetch(1);
    	if (conList.size() < 1)
    	{
    		// We have no con info? That means we have no database.
    		// That's bad, unless we're in DEV mode at the moment.
    		// Even then, that's bad. This needs to be addressed.
    		// But for now, fake it using the DF 2012 data.
    		ConInfo con = new ConInfo();
    		con.year = 2012;
    		con.month = "August";
    		con.dates = "12-14";
    		return con;
    	}
    	else
    		return (ConInfo) conList.get(0);
    }
    
    public static F.Tuple<String, String> daysCalc()
    {
    	ConInfo con = getConInfo();

		Date conDate = null;
		int startDay = Integer.parseInt(con.dates.substring(0, con.dates.indexOf("-")));
		String fullDateString = "" + startDay + " " + con.month + " " + con.year;
		try
		{
			SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy");
			conDate = sdf.parse(fullDateString);
		}
		catch (java.text.ParseException parseEx)
		{
			throw new RuntimeException("Parsing failure", parseEx);
		}
		
		String daysTo = new Integer(daysBetween(new Date(), conDate)).toString();
		String romanCon = dragonflightNumberOf(con.year);
		
		return F.T2(daysTo, romanCon);
    }
}
